﻿using System.Collections.Generic;

namespace DM4Script
{
    public partial class ScriptParse
    {
        /// primary
        ///   ::= identifierexpr
        ///   ::= numberexpr
        ///   ::= parenexpr
        private Prototypes.ExprAst ParsePrimary(Queue<string> taskExists)
        {
            switch (_curTok)
            {
                default:
                    return Error("unknown token when expecting an expression");
                case (char)Token.Identifier:
                case (char)Token.Property:
                    //return ParseIdentifierExpr();
                    return ParsesProperty(taskExists);
                case (char)Token.Number:
                    return ParseNumberExpr();
                case '(':
                    return ParseParenExpr(taskExists);

                //case (char)Token.Property: return ParsesProperty();
                //case (char)Token.If: return ParseIfExpr();
            }
        }

        
        /// binoprhs
        ///   ::= ('+' primary)*
        private Prototypes.ExprAst ParseBinOpRHS(int exprPrec, Prototypes.ExprAst lhs, Queue<string> taskExists)
        {
            // Если это бинарный оператор, получаем его приоритет
            while (true)
            {
                int tokPrec = GetTokPrecedence();

                // Если этот бинарный оператор связывает выражения по крайней мере так же, 
                // как текущий, то используем его
                if (tokPrec < exprPrec)
                    return lhs;

                // Отлично, мы знаем, что это бинарный оператор.
                string binOp = _identifierStr.ToUpperInvariant();
                GetNextToken(); // eat binop

                // Разобрать первичное выражение после бинарного оператора
                Prototypes.ExprAst rhs = ParsePrimary(taskExists);
                if (rhs == null) return null;

                // Если BinOp связан с RHS меньшим приоритетом, чем оператор после RHS, 
                // то берём часть вместе с RHS как LHS.
                int nextPrec = GetTokPrecedence();
                if (tokPrec < nextPrec)
                {
                    rhs = ParseBinOpRHS(tokPrec + 1, rhs, taskExists);
                    if (rhs == null) return null;
                }

                // Собираем LHS/RHS.
                lhs = new Prototypes.BinaryExprAst(binOp, lhs, rhs);
            }
        }
    }
}
